package com.atguigu.guli.service.trade.controller.api;


import com.atguigu.guli.service.base.feign.EduFeignClient;
import com.atguigu.guli.service.base.handler.GuliException;
import com.atguigu.guli.service.base.result.R;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.trade.entity.Order;
import com.atguigu.guli.service.trade.entity.PayLog;

import com.atguigu.guli.service.trade.service.OrderService;
import com.atguigu.guli.service.trade.service.PayLogService;
import com.atguigu.guli.service.trade.util.WxPayProperties;
import com.atguigu.utils.HttpClientUtils;
import com.atguigu.utils.StreamUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.wxpay.sdk.WXPayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/trade/wx")
public class ApiWxPayController {
    @Autowired
    WxPayProperties wxPayProperties;
    @Autowired
    OrderService orderService;
    @Autowired
    PayLogService payLogService;
    @Autowired
    EduFeignClient eduFeignClient;
    //获取wx支付二维码
    @GetMapping("auth/createNative/{orderId}")
    public R createNative(HttpServletRequest request ,  @PathVariable String orderId){
        //访问wx统一下单api
        try {
            String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            HttpClientUtils client = new HttpClientUtils(url);
            //将请求需要的参数列表转为xml文档设置到请求体中
            //参考文档将必须的参数添加到map中
            Map<String,String> map = new HashMap<>();
            map.put("appid",wxPayProperties.getAppId());//应用id
            map.put("mch_id",wxPayProperties.getPartner());//商户号
            map.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
            Order order = orderService.getById(orderId);
            map.put("body",order.getCourseTitle());
            map.put("trade_type","NATIVE");
            map.put("out_trade_no",order.getOrderNo());//订单编号
            map.put("total_fee",order.getTotalFee()+"");
            map.put("spbill_create_ip",request.getRemoteHost());//用户客户端ip
            map.put("notify_url",wxPayProperties.getNotifyUrl());//用户支付成功的回调接口
            // sign:标签数据的签名: 应用注册到wx平台时会被分配秘钥
            //使用wx工具类将map转为xml
            String xml = WXPayUtil.generateSignedXml(map, wxPayProperties.getPartnerKey());
            System.out.println("xml = " + xml);
            client.setXmlParam(xml);// 将带签名的xml类型的参数设置到请求体中
            client.post();
            //接收响应
            String content = client.getContent();
            System.out.println(content);
            //解析响应
            //1、先验证签名是否正确
            if(!WXPayUtil.isSignatureValid(content , wxPayProperties.getPartnerKey())){
                throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR );
            }
            //2、判断响应 和业务 是否成功：响应数据中的return_code 和result_code都为SUCCESS 才代表成功
            map = WXPayUtil.xmlToMap(content);
            if(!map.get("return_code").equals("SUCCESS") ||!map.get("result_code").equals("SUCCESS") ){
                throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR );
            }

            //返回链接地址 由前端js插件将链接转为wx的支付二维码图片
            return R.ok().data("code_url", map.get("code_url"))
                    .data("out_trade_no" , order.getOrderNo())
                    .data("total_fee" , order.getTotalFee())
                    .data("id" , order.getId());
        } catch (Exception e) {
            throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR , e);
        }

        //返回wx支付二维码
    }
    // http://localhost:9110/api/trade/wx/notify
    // http://577hbipk0cll.ngrok2.xiaomiqiu.cn/api/trade/wx/notify
    //回调接口：wx支付系统来调用  并传入用户支付的结果
    @PostMapping("notify")
    public String callback(HttpServletRequest request , HttpServletResponse response){
        Map<String , String> result  = new HashMap();
        result.put("return_code" , "FAIL");
        result.put("return_msg" , "未知错误");
        response.setContentType("text/xml;charset=UTF-8");//设置响应头
        //获取请求体中的数据流
        try {
            ServletInputStream is = request.getInputStream();
            String nofityStr = StreamUtils.inputStream2String(is, "UTF-8");
            System.out.println(nofityStr);
            //签名验证
            if(!WXPayUtil.isSignatureValid(nofityStr , wxPayProperties.getPartnerKey())){
                result.put("return_msg" , "签名校验失败");
                return WXPayUtil.mapToXml(result);
            }
            //xml转map
            Map<String, String> map = WXPayUtil.xmlToMap(nofityStr);
            //验证return_code和result_code为SUCCESS
            if(!map.get("return_code").equals("SUCCESS") ||!map.get("result_code").equals("SUCCESS") ){
                result.put("return_msg" , map.get("err_code_des"));
                return WXPayUtil.mapToXml(result);
            }
            //用户支付金额验证
            //查询订单
            String outTradeNo = map.get("out_trade_no");
            LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Order::getOrderNo , outTradeNo);
            Order order = orderService.getOne(queryWrapper);
            if(order.getStatus()==0){//保证幂等性：为了保证wx多次访问 只更新一次订单
                //cash_fee: 表示用户实际支付的金额
                if(order==null || order.getTotalFee()!=  Long.parseLong(map.get("cash_fee"))){
                    result.put("return_msg" , "订单金额和支付金额不一致");
                    return WXPayUtil.mapToXml(result);
                }
                //用户支付成功
                //更新订单的支付状态
                order.setStatus(1);
                order.setPayType(1);
                orderService.updateById(order);
                //保存支付日志
                PayLog payLog = new PayLog();
                String payTimeS = map.get("time_end");
                Date payTime = new SimpleDateFormat("yyyyMMddHHmmss").parse(payTimeS);
                payLog.setPayTime(payTime);
                payLog.setTradeState("已支付");
                payLog.setTotalFee(order.getTotalFee());
                payLog.setTransactionId(map.get("transaction_id"));//wx生成的交易id
                payLog.setOrderNo(order.getOrderNo());
                payLog.setPayType(1);
                payLog.setAttr(nofityStr);// wx回调时传入的数据
                payLogService.save(payLog);
                //更新课程的销量
                eduFeignClient.updateSales(order.getCourseId());

            }
            result.put("return_code" , "SUCCESS");
            result.put("return_msg" , "SUCCESS");
            return WXPayUtil.mapToXml(result);
        } catch (Exception e) {
            try {
                return WXPayUtil.mapToXml(result);
            } catch (Exception ex) {
                throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR);
            }
        }
    }
}
